package com.example.poc.food;

import java.util.List;
import java.util.Optional;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PagedResourcesAssembler;
import org.springframework.hateoas.PagedModel;
import org.springframework.stereotype.Service;

import com.example.poc.Commons;
import com.example.poc.query.FieldType;
import com.example.poc.query.FilterRequest;
import com.example.poc.query.Operator;
import com.example.poc.query.SearchRequest;
import com.example.poc.query.SearchSpecification;
import com.example.poc.query.SortDirection;
import com.example.poc.query.SortRequest;

@Service
public class FoodService {

  @Autowired
  private FoodRepository foodRepository;

  @Autowired
  private Commons commons;

  public List<Food> fetchFoodDataAsList() {
    return foodRepository.findAll();
  }

  public List<Food> fetchFilteredFoodDataAsList(String descriptionFilter) {
    return foodRepository.findByDescriptionLike(descriptionFilter);
  }

  public Page<Food> searchFood(SearchRequest request) {
    SearchSpecification<Food> specification = new SearchSpecification<>(request);
    Pageable pageable = SearchSpecification.getPageable(request.getPage(), request.getSize());
    return foodRepository.findAll(specification, pageable);
  }

  public PagedModel<FoodModel> searchFoodModel(SearchRequest request) {
    SearchSpecification<Food> specification = new SearchSpecification<>(request);
    Pageable pageable = SearchSpecification.getPageable(request.getPage(), request.getSize());
    Page<Food> foodPage = foodRepository.findAll(specification, pageable);
    FoodModelAssembler foodModelAssembler = new FoodModelAssembler();
    PagedResourcesAssembler<Food> pagedResourcesAssembler = new PagedResourcesAssembler<Food>(null, null);
    return pagedResourcesAssembler.toModel(foodPage, foodModelAssembler);
  }

  public Page<Food> fetchFoodDataAsPageWithFiltering(String descriptionFilter, int page, int size) {
    FilterRequest filterRequest = new FilterRequest("description", Operator.LIKE, FieldType.STRING, descriptionFilter, null, null);
    SearchRequest searchRequest = commons.createSearchRequest(filterRequest, null, page, size);
    return this.searchFood(searchRequest);
  }

  public Page<Food> fetchFoodDataAsPageWithFilteringAndSorting(
    String descriptionFilter,
    int page,
    int size,
    String sortColumn,
    String sortOrder
  ) {
    FilterRequest filterRequest = new FilterRequest("description", Operator.LIKE, FieldType.STRING, descriptionFilter, null, null);
    SortRequest sortRequest = new SortRequest(sortColumn, SortDirection.valueOf(sortOrder));
    SearchRequest searchRequest = commons.createSearchRequest(filterRequest, sortRequest, page, size);
    return this.searchFood(searchRequest);
  }

  public Optional<Food> findById(Long id) {
    return foodRepository.findById(id);
  }

  @Transactional
  public Food save(Food food) {
    return foodRepository.save(food);
  }

  @Transactional
  public void delete(Food food) {
    foodRepository.delete(food);
  }

}
